package com.joolun.weixin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.joolun.common.constant.Constants;
import com.joolun.common.core.redis.RedisCache;
import com.joolun.common.corp.TenantContext;
import com.joolun.common.exception.base.BaseException;
import com.joolun.common.utils.DateUtils;
import com.joolun.system.domain.*;
import com.joolun.system.mapper.ScrmCustomerMapper;
import com.joolun.system.mapper.ScrmDepartmentMapper;
import com.joolun.system.mapper.ScrmStaffMapper;
import com.joolun.system.service.impl.SysCorpConfigServiceImpl;
import com.joolun.weixin.config.WxCpConfiguration;
import com.joolun.weixin.entity.WxCustomerLossInfo;
import com.joolun.weixin.entity.dto.WxCustomerLossInfoSaveDTO;
import com.joolun.weixin.entity.dto.WxStaffDeleteCustomerDTO;
import com.joolun.weixin.service.*;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.impl.WxCpExternalContactServiceImpl;
import me.chanjar.weixin.cp.bean.external.WxCpUpdateRemarkRequest;
import me.chanjar.weixin.cp.bean.external.WxCpWelcomeMsg;
import me.chanjar.weixin.cp.bean.external.contact.ExternalContact;
import me.chanjar.weixin.cp.bean.external.contact.FollowedUser;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactBatchInfo;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RList;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 企业微信客户Service业务层处理
 * 
 * @author joolun
 * @date 2025-02-25
 */
@Service
@Slf4j
public class ScrmCustomerServiceImpl extends ServiceImpl<ScrmCustomerMapper, ScrmCustomer> implements IScrmCustomerService
{
    @Autowired
    private ScrmCustomerMapper scrmCustomerMapper;

    @Autowired
    private ScrmStaffMapper scrmStaffMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IScrmCustomerStaffService customerStaffService;
    @Autowired
    private IScrmCustomerInfoService customerInfoService;
    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ScrmDepartmentMapper scrmDepartmentMapper;

    @Autowired
    private SysCorpConfigServiceImpl sysCorpConfigService;
    /**
     * 查询企业微信客户
     *
     * @param id 企业微信客户主键
     * @return 企业微信客户
     */
    @Override
    public ScrmCustomer selectScrmCustomerById(Long id)
    {
        return scrmCustomerMapper.selectScrmCustomerById(id);
    }

    /**
     * 查询企业微信客户列表
     *
     * @param scrmCustomer 企业微信客户
     * @return 企业微信客户
     */
    @Override
    public List<ScrmCustomer> selectScrmCustomerList(ScrmCustomer scrmCustomer) {
        // 企业主体id
        scrmCustomer.setExtCorpId(TenantContext.getTenantId());
        List<ScrmCustomer>  scrmCustomers = scrmCustomerMapper.selectScrmCustomerList(scrmCustomer);
        if(CollectionUtil.isEmpty(scrmCustomers)){
            return new ArrayList<>();
        }
        List<String> extCorpIds = scrmCustomers.stream().map(item->item.getExtCorpId()).collect(Collectors.toList())
                .stream().distinct().collect(Collectors.toList());
        // 查询关联企业名称
        List<ScrmDepartment> scrmDepartments = scrmDepartmentMapper.selectList(Wrappers.lambdaQuery(ScrmDepartment.class).in(ScrmDepartment::getExtId,extCorpIds).eq(ScrmDepartment::getType,1));
        Map<String, String> nameMap = scrmDepartments.stream().collect(Collectors.toMap(
                department -> String.valueOf(department.getExtId()),
                ScrmDepartment::getName,
                (k1, k2) -> k1));

        scrmCustomers.forEach(item -> {
            String id = item.getExtCorpId();
            if(nameMap.get(id) != null){
                item.setCompanyName(nameMap.get(id));
            }
        });
        return scrmCustomers;
    }

    /**
     * 新增企业微信客户
     *
     * @param scrmCustomer 企业微信客户
     * @return 结果
     */
    @Override
    public int insertScrmCustomer(ScrmCustomer scrmCustomer)
    {
        scrmCustomer.setCreateTime(DateUtils.getNowDate());
        return scrmCustomerMapper.insertScrmCustomer(scrmCustomer);
    }

    /**
     * 修改企业微信客户
     *
     * @param scrmCustomer 企业微信客户
     * @return 结果
     */
    @Override
    public int updateScrmCustomer(ScrmCustomer scrmCustomer)
    {
        scrmCustomer.setUpdateTime(DateUtils.getNowDate());
        return scrmCustomerMapper.updateScrmCustomer(scrmCustomer);
    }

    /**
     * 批量删除企业微信客户
     *
     * @param ids 需要删除的企业微信客户主键
     * @return 结果
     */
    @Override
    public int deleteScrmCustomerByIds(Long[] ids)
    {
        return scrmCustomerMapper.deleteScrmCustomerByIds(ids);
    }

    /**
     * 删除企业微信客户信息
     *
     * @param id 企业微信客户主键
     * @return 结果
     */
    @Override
    public int deleteScrmCustomerById(Long id)
    {
        return scrmCustomerMapper.deleteScrmCustomerById(id);
    }

    @Override
    public ScrmCustomer checkExists(String id) {
        if (StringUtils.isBlank(id)) {
            return null;
        }
        ScrmCustomer byId = getById(id);
        if (byId == null || byId.getHasFriend()==0) {
            throw new BaseException("企业微信客户不存在");
        }
        return byId;
    }



//    @Override
//    public DistributedLockService.RedisLock getCustomerSyncLock(String extCorpId, String extId) {
//        return  lockService.getCustomerSyncLock(Constants.CUSTOMER_SYNC_LOCK_PRE + extCorpId + ":" + extId);
//    }
//
//
//    @Override
//    public boolean trySyncLock(DistributedLockService.RedisLock lock) throws InterruptedException {
//        boolean result = lock.lock(10, TimeUnit.SECONDS);
//        if (!result) {
//            log.error("[{}]客户同步信息尝试获取锁失败");
//        }
//        return result;
//    }
//
//    @Override
//    public void releaseSyncLock(DistributedLockService.RedisLock lock) throws InterruptedException {
//        // 判断要解锁的key是否被当前线程持有。
//        this.trySyncLock(lock);
//    }
//
//
//    @Override
//    public  List<DistributedLockService.RedisLock> getCustomerSyncLock2(String extCorpId, boolean needCache){
//        // 查出全部员工id
//        List<ScrmStaff> list = scrmStaffMapper.selectList(new QueryWrapper<ScrmStaff>().lambda()
//                .eq(ScrmStaff::getExtCorpId, extCorpId)
//                .select(ScrmStaff::getExtId));
//        List<String> staffExtIds = list.stream().map(ScrmStaff::getExtId).collect(Collectors.toList());
//
//        // 批量遍历同步数据（每次同步100个员工的客户数据）
//        WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getCustomerSecretWxCpService());
//
//        Set<String> customerExtIds = new HashSet<>();
//
//        // 调用批量获取客户信息接口（每次最多只能获取100条数据，因此得递归分页获取所有的）
//        Lists.partition(staffExtIds, 100).forEach(staffIds -> {
//            WxCpExternalContactBatchInfo contactDetailBatch = null;
//            try {
//                // 调用企业微信接口，批量获取客户详情
//                contactDetailBatch = externalContactService.getContactDetailBatch(staffIds.toArray(new String[0]), null, 100);
//                List<WxCpExternalContactBatchInfo.ExternalContactInfo> externalContactList = contactDetailBatch.getExternalContactList();
//                // 调用
//                this.getContactDetailBatch(externalContactService, externalContactList, staffIds, contactDetailBatch.getNextCursor());
//                externalContactList.forEach(e -> customerExtIds.add(e.getExternalContact().getExternalUserId()));
//                // 把信息放入缓存
//                if (needCache) {
//                    // 获取名称为 "objectList" 的RList实例
//                    List<WxCpExternalContactBatchInfo.ExternalContactInfo> rList = redisCache.getCacheList(Constants.WX_CUSTOMER_SYNC_INFOS + extCorpId);
//                    // 清空已存在的列表数据
//                    rList.clear();
//                    if (CollectionUtil.isNotEmpty(externalContactList)) {
//                        // 将对象列表添加到RList中
//                        rList.addAll(externalContactList);
//                    }
//                }
//            } catch (WxErrorException e) {
//                log.error("获取客户信息失败！", e);
//                throw new BaseException(ErrorMsgEnum.CODE_90003.getMsg(),e.getMessage());
//            }
//        });
//
//        // 每个员工都上锁
//        return customerExtIds.stream().map(e -> getCustomerSyncLock(extCorpId, e)).collect(Collectors.toList());
//    }



//    @Override
//    public   List<RLock>  getCustomerSyncLock(String extCorpId, boolean needCache) {
//        // 查出全部员工id
//        List<ScrmStaff> list = scrmStaffMapper.selectList(new QueryWrapper<ScrmStaff>().lambda()
//                .eq(ScrmStaff::getExtCorpId, extCorpId)
//                .select(ScrmStaff::getExtId));
//        List<String> staffExtIds = list.stream().map(ScrmStaff::getExtId).collect(Collectors.toList());
//
//        // 批量遍历同步数据（每次同步100个员工的客户数据）
//        WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getWxCpService());
//
//        List<String> customerExtIds = new HashSet<>();
//
//        // 调用批量获取客户信息接口（每次最多只能获取100条数据，因此得递归分页获取所有的）
//        Lists.partition(staffExtIds, 100).forEach(staffIds -> {
//             WxCpExternalContactBatchInfo contactDetailBatch = null;
//             try {
//                 // 调用企业微信接口，批量获取客户详情
//                 contactDetailBatch = externalContactService.getContactDetailBatch(staffIds.toArray(new String[0]), null, 100);
//                 List<WxCpExternalContactBatchInfo.ExternalContactInfo> externalContactList = contactDetailBatch.getExternalContactList();
//                 // 调用
//                 this.getContactDetailBatch(externalContactService, externalContactList, staffIds, contactDetailBatch.getNextCursor());
//                 externalContactList.forEach(e -> customerExtIds.add(e.getExternalContact().getExternalUserId()));
//                 // 把信息放入缓存
//                 if (needCache) {
//                     // 获取名称为 "objectList" 的RList实例
//                     List<WxCpExternalContactBatchInfo.ExternalContactInfo> rList = redisCache.getCacheList(Constants.WX_CUSTOMER_SYNC_INFOS + extCorpId);
//                     // 清空已存在的列表数据
//                     rList.clear();
//                     if (CollectionUtil.isNotEmpty(externalContactList)) {
//                         // 将对象列表添加到RList中
//                         rList.addAll(externalContactList);
//                     }
//                 }
//             } catch (WxErrorException e) {
//                 log.error("获取客户信息失败！", e);
//                 throw new BaseException(ErrorMsgEnum.CODE_90003.getMsg(),e.getMessage());
//             }
//         });
//
//        // 每个员工都上锁
//
//        return customerExtIds;
//    }

    @Override
    public void sync(String extCorpId, boolean isSync)  {

        List<WxCpExternalContactBatchInfo.ExternalContactInfo> allExternalContactList = new ArrayList<>();

        // 获取该企业，状态为未退出企业的员工
        List<ScrmStaff> scrmStaffs = scrmStaffMapper.selectList(new LambdaQueryWrapper<ScrmStaff>().eq(ScrmStaff::getExtCorpId, extCorpId)
                // .ne(Staff::getStatus, 5)
        );
        // 企业员工信息ID
        List<String> staffExtIds = scrmStaffs.stream().map(ScrmStaff::getExtId).filter(StringUtils::isNotBlank).collect(Collectors.toList());
        // 设置每批的大小为100
        int batchSize = 100;
        // 使用 Guava 的 Lists.partition 来分割列表
        List<List<String>> batchStaffIds = Lists.partition(staffExtIds, batchSize);

        Date deleteAt = new Date();

        if (isSync) {
            // 获取主体配置
            SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(TenantContext.getTenantId());
            // 声明调用企业微信的service
            WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getWxCpService(sysCorpConfig));
            String firstNextCursor = "";

            AtomicInteger batchCount = new AtomicInteger();
            // 处理每个批次
            batchStaffIds.forEach(staffIds -> {
                // 首次分页游标为空
                String nextCursor = firstNextCursor;
                do {
                    try {
                        log.info("当前游标：{},员工id：{}",nextCursor,staffIds.toString());
                        // 调用批量获取客户信息接口（每次最多只能获取100条数据，因此得递归分页获取所有的）
                        WxCpExternalContactBatchInfo contactDetailBatch = externalContactService.getContactDetailBatch(staffIds.toArray(new String[0]), nextCursor, 100);
                        // 当次的客户的基本信息
                        List<WxCpExternalContactBatchInfo.ExternalContactInfo> externalContactList = contactDetailBatch.getExternalContactList();
                        // 更新分页游标
                        nextCursor = contactDetailBatch.getNextCursor();
                        if (CollectionUtil.isNotEmpty(externalContactList)) {
                            allExternalContactList.addAll(externalContactList);
                        }
                    } catch (WxErrorException e) {
                        // 处理异常，例如记录日志或抛出运行时异常
                        log.error("同步客户信息失败，企业ID：【{}】,异常信息：【{}】", extCorpId, e);
                        throw new BaseException("同步客户信息异常");
                    }
                } while (nextCursor != null && !nextCursor.isEmpty()); // 继续循环直到没有更多数据
                batchCount.addAndGet(staffIds.size());
                log.info("【同步客户】员工数量：{}，客户数量：{}", batchCount, allExternalContactList.size());
            });

        } else {
            // 取缓存的客户数据
            List<WxCpExternalContactBatchInfo.ExternalContactInfo> rList = redisCache.getCacheList(Constants.WX_CUSTOMER_SYNC_INFOS + extCorpId);
            allExternalContactList.addAll(rList);
        }

        log.info("-------获取企业微信员工客户数据完成-------:");


        // 还存在的客户extId列表
        List<String> existCustomerExtIds = new ArrayList<>();

        AtomicInteger count = new AtomicInteger();

        // 获取到的客户信息分批次处理入库
        List<List<WxCpExternalContactBatchInfo.ExternalContactInfo>>  batchCompareList = Lists.partition(allExternalContactList,100);

        batchCompareList.forEach(externalContactInfo100 -> {
            log.info("-------按100个批次处理-------{}:",count.getAndIncrement());
            // 刷新客户信息，客户-标签关联，比较新增或更新
            refreshCustomers(externalContactInfo100, extCorpId);
        });


            // 移除不存在的客户信息（移除客户，客户跟进情况，客户详情，客户-标签，员工客户数量）
//            List<String> allCustomerExtIds = Optional.ofNullable(list(new LambdaQueryWrapper<ScrmCustomer>().select(ScrmCustomer::getExtId).eq(ScrmCustomer::getExtCorpId, extCorpId).eq(ScrmCustomer::getHasFriend, true)))
//                    .orElse(new ArrayList<>()).stream().map(ScrmCustomer::getExtId).collect(Collectors.toList());
//            allCustomerExtIds.removeAll(existCustomerExtIds);

//            if (CollectionUtil.isNotEmpty(allCustomerExtIds)) {
//                // 移除客户
//                update(new LambdaUpdateWrapper<ScrmCustomer>()
//                        .eq(ScrmCustomer::getExtCorpId, extCorpId)
//                        .in(ScrmCustomer::getExtId, allCustomerExtIds)
//                        .set(ScrmCustomer::getStatus, null)
//                        .set(ScrmCustomer::getDeletedAt, deleteAt));

                // 移除客户-标签
//                customerStaffTagService.update(new LambdaUpdateWrapper<WxCustomerStaffTag>()
//                        .eq(WxCustomerStaffTag::getExtCorpId, extCorpId)
//                        .in(WxCustomerStaffTag::getExtCustomerId, allCustomerExtIds)
//                        .set(WxCustomerStaffTag::getHasDelete, null)
//                        .set(WxCustomerStaffTag::getDeletedAt, deleteAt));

                // 移除客户跟进情况
//                customerStaffService.update(new LambdaUpdateWrapper<ScrmCustomerStaff>()
//                        .eq(ScrmCustomerStaff::getExtCorpId, extCorpId)
//                        .in(ScrmCustomerStaff::getExtCustomerId, allCustomerExtIds)
//                        .set(ScrmCustomerStaff::getHasDelete, null)
//                        .set(ScrmCustomerStaff::getDeletedAt, deleteAt));
//
//                // 移除客户详情
//                customerInfoService.update(new LambdaUpdateWrapper<ScrmCustomerInfo>()
//                        .eq(ScrmCustomerInfo::getExtCorpId, extCorpId)
//                        .in(ScrmCustomerInfo::getExtCustomerId, allCustomerExtIds)
//                        .set(ScrmCustomerInfo::getHasDelete, null)
//                        .set(ScrmCustomerInfo::getDeletedAt, deleteAt));
//            }

//            staffExtIdAndCustomerExtIdsMap.forEach((key, value) -> {
                // 移除客户-标签
//                customerStaffTagService.update(new LambdaUpdateWrapper<WxCustomerStaffTag>()
//                        .eq(WxCustomerStaffTag::getExtCorpId, extCorpId)
//                        .eq(WxCustomerStaffTag::getExtStaffId, key)
//                        .notIn(ListUtils.isNotEmpty(value), WxCustomerStaffTag::getExtCustomerId, value)
//                        .set(WxCustomerStaffTag::getHasDelete, null)
//                        .set(WxCustomerStaffTag::getDeletedAt, deleteAt));

                // 移除客户跟进情况
//                customerStaffService.update(new LambdaUpdateWrapper<ScrmCustomerStaff>()
//                        .eq(ScrmCustomerStaff::getExtCorpId, extCorpId)
//                        .eq(ScrmCustomerStaff::getExtStaffId, key)
//                        .notIn(CollectionUtil.isNotEmpty(value), ScrmCustomerStaff::getExtCustomerId, value)
//                        .set(ScrmCustomerStaff::getHasDelete, null)
//                        .set(ScrmCustomerStaff::getDeletedAt, deleteAt));
//
//                // 移除客户详情
//                customerInfoService.update(new LambdaUpdateWrapper<ScrmCustomerInfo>()
//                        .eq(ScrmCustomerInfo::getExtCorpId, extCorpId)
//                        .eq(ScrmCustomerInfo::getExtStaffId, key)
//                        .notIn(CollectionUtil.isNotEmpty(value), ScrmCustomerInfo::getExtCustomerId, value)
//                        .set(ScrmCustomerInfo::getHasDelete, null)
//                        .set(ScrmCustomerInfo::getDeletedAt, deleteAt));

//            });

//            // 刷新员工客户数量
//            Optional.ofNullable(customerStaffService.countGroupByStaffExtId(extCorpId)).orElse(new ArrayList<>())
//                    .forEach(countVO -> scrmStaffMapper.update(new LambdaUpdateWrapper<ScrmStaff>().eq(ScrmStaff::getExtCorpId, extCorpId)
//                                    .eq(ScrmStaff::getExtId, countVO.getExtStaffId())
//                                    .set(ScrmStaff::getCustomerCount, Optional.ofNullable(countVO.getTotal()).orElse(0))));


    }




    public void refreshCustomers(List<WxCpExternalContactBatchInfo.ExternalContactInfo> externalContactInfos, String extCorpId) {
        // 收集所有客户外部 ID 和员工外部 ID
        List<String> customerExtIds = externalContactInfos.stream()
                .map(info -> info.getExternalContact().getExternalUserId())
                .collect(Collectors.toList());
        List<String> staffExtIds = externalContactInfos.stream()
                .map(info -> info.getFollowInfo().getUserId())
                .collect(Collectors.toList());

        // 批量查询本地已存在的客户信息
        Map<String, ScrmCustomer> existingCustomerMap = batchCheckCustomers(extCorpId, customerExtIds,staffExtIds);

        // 批量查询客户员工跟进信息
        Map<String, ScrmCustomerStaff> existingCustomerStaffMap = batchCheckCustomerStaffs(extCorpId, customerExtIds, staffExtIds);

        // 需要新增、更新的客户列表
        List<ScrmCustomer> customersToInsert = new ArrayList<>();
        List<ScrmCustomer> customersToUpdate = new ArrayList<>();

        // 需要新增、更新的客户员工跟进信息列表
        List<ScrmCustomerStaff> staffsToInsert = new ArrayList<>();
        List<ScrmCustomerStaff> staffsToUpdate = new ArrayList<>();

        // 需要更新客户数的员工列表
        Map<String, Integer> staffCustomerCountMap = new HashMap<>();

        // 遍历接口返回的客户信息
        for (WxCpExternalContactBatchInfo.ExternalContactInfo externalContactInfo : externalContactInfos) {
            // 客户的基本信息
            ExternalContact externalContact = externalContactInfo.getExternalContact();
            // 企业成员客户跟进信息
            FollowedUser followInfo = externalContactInfo.getFollowInfo();

            String operatorUserId = followInfo.getOperatorUserId();
            String staffExtId = followInfo.getUserId();
            String customerExtId = externalContact.getExternalUserId();

            // 更新客户信息
            String customerKey = customerExtId + "_" + staffExtId; // 组合键
            ScrmCustomer existingCustomer = existingCustomerMap.get(customerKey);

           // ScrmCustomer existingCustomer = existingCustomerMap.get(customerExtId);
            ScrmCustomer customer = new ScrmCustomer();
            BeanUtils.copyProperties(externalContact, customer);
            customer.setUnionid(externalContact.getUnionId());
            customer.setExtCorpId(extCorpId);
            customer.setExtId(customerExtId);
            if(externalContact.getExternalProfile()!=null){
                customer.setExternalProfile(JSONObject.toJSONString(externalContact.getExternalProfile()));
            }
            if (existingCustomer != null) {
//                if(existingCustomer.getAvatar().equals(externalContact.getAvatar())){
//                    continue;
//                }
                // TODO：这里也可以比较判断是否需要更新
                customer.setUpdatedAt(new Date());
                customer.setIsDeletedStaff(existingCustomer.getIsDeletedStaff());
                customer.setExtCreatorId(existingCustomer.getExtCreatorId());
                // 该成员添加此外部联系人的时间
                customer.setCreatedAt(new Date(followInfo.getCreateTime() * 1000));
                customer.setId(existingCustomer.getId());
                customer.setGender(externalContact.getGender());
                customer.setAvatar(externalContact.getAvatar());
                customersToUpdate.add(customer);
            } else {
                customer.setExtCreatorId(staffExtId);
                customer.setCreateTime(new Date(followInfo.getCreateTime() * 1000));
                customersToInsert.add(customer);
            }

            // 更新客户员工跟进信息
            String customerStaffKey = customerExtId + "_" + staffExtId;
            ScrmCustomerStaff existingCustomerStaff = existingCustomerStaffMap.get(customerStaffKey);
            ScrmCustomerStaff customerStaff = new ScrmCustomerStaff();
            BeanUtils.copyProperties(followInfo, customerStaff);
            customerStaff.setOperUserId(operatorUserId);
            customerStaff.setRemarkMobiles(followInfo.getRemarkMobiles() != null ? Arrays.toString(followInfo.getRemarkMobiles()) : "");
            customerStaff.setExtCreatorId(customer.getExtCreatorId());
            customerStaff.setRemarkCorpName(followInfo.getRemarkCompany());
            customerStaff.setExtStaffId(staffExtId);
            customerStaff.setExtCustomerId(customerExtId);
            customerStaff.setCustomerId(customer.getId() + "");
            customerStaff.setExtCorpId(extCorpId);
            customerStaff.setCreateTime(new Date(followInfo.getCreateTime() * 1000));
            customerStaff.setCreatedAt(new Date(followInfo.getCreateTime() * 1000));
            customerStaff.setDescription(followInfo.getDescription());

            if (existingCustomerStaff != null) {
//                if(existingCustomerStaff.getRemark().equals(followInfo.getRemark())){
//                    log.info("---followinfo:{}", JSONObject.toJSONString(followInfo));
//                    continue;
//                }
                customerStaff.setCreatedAt(existingCustomerStaff.getCreatedAt())
                        .setIsDeletedStaff(existingCustomerStaff.getIsDeletedStaff())
                        .setUpdatedAt(new Date())
                        .setId(existingCustomerStaff.getId());
                staffsToUpdate.add(customerStaff);
            } else {
                staffsToInsert.add(customerStaff);

                // 统计员工客户数增量
                staffCustomerCountMap.put(staffExtId, staffCustomerCountMap.getOrDefault(staffExtId, 0) + 1);
            }
        }

        // 批量操作
        if (!customersToInsert.isEmpty()) {
            saveBatch(customersToInsert);
        }
        if (!customersToUpdate.isEmpty()) {
            updateBatchById(customersToUpdate);
        }
        // TODO：重复同步的时候查看这个关联数据是否会重复插入
        if (!staffsToInsert.isEmpty()) {
            customerStaffService.saveBatch(staffsToInsert);
        }
        if (!staffsToUpdate.isEmpty()) {
            customerStaffService.updateBatchById(staffsToUpdate);
        }

        // 批量更新员工客户数
        staffCustomerCountMap.forEach((staffExtId, count) -> {
            ScrmStaff staff = scrmStaffMapper.selectOne(new QueryWrapper<ScrmStaff>()
                    .lambda()
                    .eq(ScrmStaff::getExtId, staffExtId)
                    .eq(ScrmStaff::getExtCorpId, extCorpId));
            if (staff != null) {
                staff.setCustomerCount(Optional.ofNullable(staff.getCustomerCount()).orElse(0) + count);
                scrmStaffMapper.updateById(staff);
            }
        });
    }

    public Map<String, ScrmCustomer> batchCheckCustomers(String extCorpId, List<String> customerExtIds, List<String> staffExtIds) {
        // 使用 IN 语句批量查询客户信息
        List<ScrmCustomer> existingCustomers = scrmCustomerMapper.selectList(new QueryWrapper<ScrmCustomer>()
                .eq("ext_corp_id", extCorpId)
                .in("ext_id", customerExtIds));

        // 将查询结果按组合键分组
        return existingCustomers.stream()
                .collect(Collectors.toMap(
                        customer -> customer.getExtId() + "_" + customer.getExtCreatorId(), // 组合键
                        customer -> customer
                ));
    }
    public Map<String, ScrmCustomerStaff> batchCheckCustomerStaffs(String extCorpId, List<String> customerExtIds, List<String> staffExtIds) {
        // 使用 IN 语句批量查询客户员工跟进信息
        List<ScrmCustomerStaff> existingCustomerStaffs = customerStaffService.list(new QueryWrapper<ScrmCustomerStaff>()
                .eq("ext_corp_id", extCorpId)
                .in("ext_customer_id", customerExtIds)
                .in("ext_staff_id", staffExtIds));

        // 将查询结果按客户外部 ID 和员工外部 ID 分组
        return existingCustomerStaffs.stream()
                .collect(Collectors.toMap(
                        staff -> staff.getExtCustomerId() + "_" + staff.getExtStaffId(),
                        staff -> staff
                ));
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void sendWelcomeMsg(WxCpWelcomeMsg msg) {

        try {
            WxCpExternalContactService externalContactService = getWxCpExternalContactService();
            externalContactService.sendWelcomeMsg(msg);
        } catch (WxErrorException e) {
            log.error("[{}]发送新客户欢迎语失败，", JSON.toJSONString(msg), e);
        }

    }

    private WxCpExternalContactService getWxCpExternalContactService() {
        // 获取主体配置
        SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(TenantContext.getTenantId());
        return new WxCpExternalContactServiceImpl(WxCpConfiguration.getCustomerSecretWxCpService(sysCorpConfig));
    }

    @Override
    public WxCpExternalContactInfo getCustomInfo(String userId) {
        WxCpExternalContactService externalContactService = getWxCpExternalContactService();
        try {
            return externalContactService.getContactDetail(userId, null);
        } catch (WxErrorException e) {
            e.printStackTrace();
            return null;
        }
    }




    @Override
    public void staffDeleteCustomer(WxStaffDeleteCustomerDTO customerDTO) {

        Date deleteAt = new Date();
        // 1、新增流水
        ScrmStaff staff = scrmStaffMapper.selectOne(Wrappers.lambdaQuery(ScrmStaff.class).eq(ScrmStaff::getExtCorpId,customerDTO.getExtCorpId())
                .eq(ScrmStaff::getExtId,customerDTO.getStaffExtId()));

        ScrmCustomer wxCustomer = scrmCustomerMapper.selectOne(Wrappers.lambdaQuery(ScrmCustomer.class)
                .eq(ScrmCustomer::getExtCorpId,customerDTO.getExtCorpId())
                .eq(ScrmCustomer::getExtId,customerDTO.getCustomerExtId()));

        ScrmCustomerStaff customerStaff = customerStaffService.checkExists(wxCustomer.getExtCorpId(), staff.getExtId(),
                wxCustomer.getExtId());

//        WxCustomerLossInfoSaveDTO wxCustomerLossInfoSaveDTO = new WxCustomerLossInfoSaveDTO()
//                .setDeleteByTransfer(customerDTO.getDeleteByTransfer())
//                .setStaffId(staff.getId()+"")
//                .setCustomerId(wxCustomer.getId()+"")
//                .setCustomerStaffId(customerStaff.getId()+"")
//                .setExtCorpId(customerDTO.getExtCorpId())
//                .setCreateTime(new Date())
//                .setType(customerDTO.getType())
//                .setDeleteTime(customerDTO.getDeleteTime())
//                .setAddTime(customerStaff.getCreateTime())
//                .setExtCustomerId(wxCustomer.getExtId());

        // 客户删除员工
        if (Objects.equals(WxCustomerLossInfo.TYPE_CUSTOMER_DELETE_STAFF, customerDTO.getType())) {
            log.info("客户删除员工");
            customerStaff.setIsDeletedStaff(true).setUpdatedAt(new Date());
            customerStaffService.updateById(customerStaff);

            if (OptionalLong.of(customerStaffService.count(new LambdaQueryWrapper<ScrmCustomerStaff>()
                            .eq(ScrmCustomerStaff::getExtCorpId, customerDTO.getExtCorpId())
                            .eq(ScrmCustomerStaff::getExtCustomerId, wxCustomer.getExtId())
                            .and(wrapper -> wrapper.eq(ScrmCustomerStaff::getIsDeletedStaff, false).or()
                                    .isNull(ScrmCustomerStaff::getIsDeletedStaff))))
                    .orElse(0) < 1) {
                wxCustomer.setIsDeletedStaff(0);
                updateById(wxCustomer);
            }
        } else {
            log.info("员工删除客户");
            // 2、判断是否还有别的跟进人员，如果有则删除跟进关系、从客户旅程中移除，如果没有删除跟进关系,客户信息,客户详情信息,客户-标签
            if (OptionalLong.of(customerStaffService.count(new LambdaQueryWrapper<ScrmCustomerStaff>()
                    .eq(ScrmCustomerStaff::getExtCorpId, customerDTO.getExtCorpId())
                    .eq(ScrmCustomerStaff::getExtCustomerId, customerDTO.getCustomerExtId()))).orElse(0) < 2) {

                // 删除客户
                update(new LambdaUpdateWrapper<ScrmCustomer>()
                        .eq(ScrmCustomer::getId, wxCustomer.getId())
                        .set(ScrmCustomer::getDeletedAt, deleteAt));
                removeById(wxCustomer.getId());

                // 记录删除的时候的客户旅程信息
//                wxCustomerLossInfoSaveDTO.setJourneyStageIds(Optional.ofNullable(journeyStageCustomerService.list(
//                                new LambdaQueryWrapper<BrJourneyStageCustomer>()
//                                        .eq(BrJourneyStageCustomer::getExtCorpId, customerDTO.getExtCorpId())
//                                        .eq(BrJourneyStageCustomer::getCustomerExtId, wxCustomer.getExtId())))
//                        .orElse(new ArrayList<>()).stream().map(BrJourneyStageCustomer::getJourneyStageId)
//                        .collect(Collectors.toList()));
//                journeyStageCustomerService.remove(new LambdaQueryWrapper<BrJourneyStageCustomer>()
//                        .eq(BrJourneyStageCustomer::getExtCorpId, customerDTO.getExtCorpId())
//                        .eq(BrJourneyStageCustomer::getCustomerExtId, wxCustomer.getId()));
            }
            if (null !=customerStaff.getId()) {
                // 删除客户-员工关联
                customerStaffService.update(new LambdaUpdateWrapper<ScrmCustomerStaff>()
                        .eq(ScrmCustomerStaff::getId, customerStaff.getId())
                        .set(ScrmCustomerStaff::getDeletedAt, deleteAt));
                customerStaffService.removeById(customerStaff.getId());

                // 员工-客户-详情
                customerInfoService.update(new LambdaUpdateWrapper<ScrmCustomerInfo>()
                        .eq(ScrmCustomerInfo::getExtCorpId, customerStaff.getExtCorpId())
                        .eq(ScrmCustomerInfo::getExtStaffId, customerStaff.getExtStaffId())
                        .eq(ScrmCustomerInfo::getExtCustomerId, customerStaff.getExtCustomerId())
                        .set(ScrmCustomerInfo::getDeletedAt, deleteAt));
                customerInfoService.remove(new LambdaQueryWrapper<ScrmCustomerInfo>()
                        .eq(ScrmCustomerInfo::getExtCorpId, customerStaff.getExtCorpId())
                        .eq(ScrmCustomerInfo::getExtStaffId, customerStaff.getExtStaffId())
                        .eq(ScrmCustomerInfo::getExtCustomerId, customerStaff.getExtCustomerId()));

            }

            // 3、更新员工的客户数
            staff.setCustomerCount(
                    Math.toIntExact(OptionalLong.of(customerStaffService.count(new LambdaQueryWrapper<ScrmCustomerStaff>()
                            .eq(ScrmCustomerStaff::getExtCorpId, wxCustomer.getExtCorpId())
                            .eq(ScrmCustomerStaff::getExtStaffId, staff.getExtId()))).orElse(0)));
            scrmStaffMapper.updateById(staff);
        }

//        WxCustomerLossInfo wxCustomerLossInfo = customerLossInfoService.save(wxCustomerLossInfoSaveDTO.setStaffExtId(staff.getExtId()));
//        log.info("新增流失记录,入参：【{}】,出参【{}】", wxCustomerLossInfoSaveDTO, wxCustomerLossInfo);

    }











}
